import {getToken} from "@/utils/auth";

export class SocketWorker {
  constructor(url) {
    this.url = url
    this.worker = new Worker(new URL('./socketIO.worker.js', import.meta.url), {type: 'module'})
    this.worker.postMessage({
      eventType: 'build',
      content: {
        url: this.url,
        token: getToken()
      }
    })
    this.worker.addEventListener('message', ({ data }) => {
      const { eventType, content } = data

      if (eventType === 'result') {
        const { event, result } = content
        const callback = this.eventMap.get(event)
        if (callback && typeof callback === 'function') {
          callback(result)
        }
      }
    })

    this.eventMap = new Map()
  }

  connect() {
    return new Promise((resolve, reject) => {
      const listener = ({data}) => {
        this.worker.removeEventListener('message', listener)
        const {eventType} = data
        if (eventType === 'connected') {
          resolve(true)
        } else {
          reject(true)
        }
      }

      this.worker.addEventListener('message', listener)

      this.worker.postMessage({
        eventType: 'connect'
      })
    })
  }

  on(event, callback) {
    this.off(event)
    this.eventMap.set(event, callback)
    this.worker.postMessage({
      eventType: 'on',
      content: {event}
    })
  }

  off(event) {
    this.eventMap.delete(event)
    this.worker.postMessage({
      eventType: 'off',
      content: {event}
    })
  }

  emit(event, data) {
    this.worker.postMessage({
      eventType: 'emit',
      content: {
        event,
        data
      }
    })
  }

  disconnect() {
    return new Promise((resolve, reject) => {
      const listener = ({data}) => {
        this.worker.removeEventListener('message', listener)
        const {eventType} = data
        if (eventType === 'disconnected') {
          resolve(true)
        } else {
          reject(false)
        }
      }

      this.worker.addEventListener('message', listener)

      this.worker.postMessage({
        eventType: 'disconnect'
      })
    })
  }
}
